import bpy
import os
from xml.dom.minidom import Document

#   Globals
ActiveFile = str(bpy.data.filepath).split("\\")[len(str(bpy.data.filepath).split("\\"))-1][:-6]
WorkingPath = 'C:\\Users\\Björn\\Desktop\\Heroic Hearts\\' + ActiveFile + '.txt'
file = open(WorkingPath, "w")
sceneHolder = []

#   Structures
class Vector2:
    x = 0.0
    y = 0.0

class Vector3:
    x = 0.0
    y = 0.0
    z = 0.0
    def __init__(self, theX=0, theY=0, theZ=0):
        self.x = theX
        self.y = theY
        self.z = theZ
    def setValues(self, theX, theY, theZ):
        self.x = theX
        self.y = theY
        self.z = theZ
    
class Vector4:
    x = 0.0
    y = 0.0
    z = 0.0
    w = 0.0
    def setValues(self, theX, theY, theZ, theW):
        self.x = theX
        self.y = theY
        self.z = theZ
        self.w = theW

class Vertex:
    position = Vector3()
    normal = Vector3()
    def __init__(self, theX=0, theY=0, theZ=0, theNormalX=0, theNormalY=0, theNormalZ=0):
        self.position = Vector3()
        self.position.x = theX
        self.position.y = theY
        self.position.z = theZ
        self.normal = Vector3()
        self.normal.x = theNormalX
        self.normal.y = theNormalY
        self.normal.z = theNormalZ

class Texture:
    name = ""
    filePath = ""

class Material:
    name = ""
    vertices = []
    color = Vector4()
    textures = []
    def __init__(self):
        self.vertices = []
        self.color = Vector4()
        self.name = ""
        self.textures = []
        
class Mesh:
    name = ""
    materials = []
    def __init__(self):
        self.materials = []
        self.name = ""

class Camera:
    location = Vector3()
    rotation = Vector4()
    def __init__(self):
        self.location = Vector3()
    def printToFile(self):
        return( str(self.location.x) + '\n' + str(self.location.y) + '\n' + str(self.location.z) + '\n')

class Lamp:
    location = Vector3()
    def __init__(self):
        self.location = Vector3()

class Scene:
    cameras = []
    meshes = []
    lamps = []
    def __init__(self):
        self.cameras = []
        self.meshes = []
        self.lamps = []
        self.name = ""

#   CreateFolder
#   Creates a folder with the specified name in the WorkingPath
#   after checking if it exists.
def CreateFolder(FolderName):
    if not os.path.exists(WorkingPath + FolderName):
        os.makedirs(WorkingPath + FolderName)

def HandleCameraObject():
    tempCamera = Camera()
    object.rotation_mode = 'QUATERNION'
    tempCamera.location.setValues(object.location.x, object.location.y, object.location.z)
    tempCamera.rotation.setValues(object.rotation_quaternion.x, object.rotation_quaternion.y, object.rotation_quaternion.z, object.rotation_quaternion.w)
    tempScene.cameras.append(tempCamera)
    
def HandleMeshObject():
    tempMesh = Mesh()
    tempMesh.name = object.name
    for material in object.data.materials:
        tempMaterial = Material()
        tempMaterial.name = material.name
        for texName in material.texture_slots.keys():
            tempTex = Texture()
            tempTex.name = texName
            print(tempTex.name)
            tempTex.filePath = material.texture_slots[texName].texture.image.name
            tempMaterial.textures.append(tempTex)
        tempMaterial.color.x = material.diffuse_color.r
        tempMaterial.color.y = material.diffuse_color.g
        tempMaterial.color.z = material.diffuse_color.b
        tempMesh.materials.append(tempMaterial)
    for polygon in object.data.polygons:
        materialIndex = polygon.material_index
        if len(polygon.vertices) == 3:
            pass
        elif len(polygon.vertices) == 4:
            pol0 = polygon.vertices[0]
            pol1 = polygon.vertices[1]
            pol2 = polygon.vertices[2]            
            pol3 = polygon.vertices[3]                                 
            tempMesh.materials[materialIndex].vertices.append(Vertex(object.data.vertices[pol3].co.x, object.data.vertices[pol3].co.y, object.data.vertices[pol3].co.z, polygon.normal.x, polygon.normal.y, polygon.normal.z ))
            tempMesh.materials[materialIndex].vertices.append(Vertex(object.data.vertices[pol2].co.x, object.data.vertices[pol2].co.y, object.data.vertices[pol2].co.z, polygon.normal.x, polygon.normal.y, polygon.normal.z ))
            tempMesh.materials[materialIndex].vertices.append(Vertex(object.data.vertices[pol0].co.x, object.data.vertices[pol0].co.y, object.data.vertices[pol0].co.z, polygon.normal.x, polygon.normal.y, polygon.normal.z ))
            tempMesh.materials[materialIndex].vertices.append(Vertex(object.data.vertices[pol2].co.x, object.data.vertices[pol2].co.y, object.data.vertices[pol2].co.z, polygon.normal.x, polygon.normal.y, polygon.normal.z ))
            tempMesh.materials[materialIndex].vertices.append(Vertex(object.data.vertices[pol1].co.x, object.data.vertices[pol1].co.y, object.data.vertices[pol1].co.z, polygon.normal.x, polygon.normal.y, polygon.normal.z ))
            tempMesh.materials[materialIndex].vertices.append(Vertex(object.data.vertices[pol0].co.x, object.data.vertices[pol0].co.y, object.data.vertices[pol0].co.z, polygon.normal.x, polygon.normal.y, polygon.normal.z ))
        else:
            print('Polygon length not supported')
    tempScene.meshes.append(tempMesh)

def HandleLampObject():
    tempLamp = Lamp()
    tempLamp.location.x = object.location.x
    tempLamp.location.y = object.location.y    
    tempLamp.location.z = object.location.z    
    tempScene.lamps.append(tempLamp)
    
#   Iterate over all the scenes in the file
for scene in bpy.data.scenes:
    #   Buffer for all the scene data
    tempScene = Scene()
    tempScene.name = scene.name
    #   Iterate over all the objects in the scene and add them to the Scene object
    for object in scene.objects:
        if object.type == 'CAMERA':
            HandleCameraObject()
        elif object.type == 'MESH':
            HandleMeshObject()
        elif object.type == 'LAMP':
            HandleLampObject()
        else:
            print("Object of type " + object.type + " not supported yet.")         
    sceneHolder.append(tempScene)

#Root XMLDocument    
doc = Document()
for xmlScene in sceneHolder:
    scene = doc.createElement("Scene")
    scene.setAttribute("name", xmlScene.name)
    doc.appendChild(scene)
    
    sceneInfo = doc.createElement("Properties")
    scene.appendChild(sceneInfo)
    
    sceneMeshes = doc.createElement("NumberOfMeshes")
    sceneInfo.appendChild(sceneMeshes)
    sceneMeshesText = doc.createTextNode(str(len(xmlScene.meshes)))
    sceneMeshes.appendChild(sceneMeshesText)
    
    sceneCameras = doc.createElement("NumberOfCameras")
    sceneInfo.appendChild(sceneCameras)
    sceneCamerasText = doc.createTextNode(str(len(xmlScene.cameras)))
    sceneCameras.appendChild(sceneCamerasText)
    
    sceneLamps = doc.createElement("NumberOfLamps")
    sceneInfo.appendChild(sceneLamps)
    sceneLampsText = doc.createTextNode(str(len(xmlScene.lamps)))
    sceneLamps.appendChild(sceneLampsText)
    
    objects = doc.createElement("Objects")
    scene.appendChild(objects)
    for xmlModel in xmlScene.meshes:
        model = doc.createElement("Model")
        model.setAttribute("name", xmlModel.name)
        objects.appendChild(model)
        
        modelInfo = doc.createElement("Properties")
        model.appendChild(modelInfo)
        
        modelMaterials = doc.createElement("NumberOfMaterials")
        modelInfo.appendChild(modelMaterials)
        modelNumberMaterials = doc.createTextNode(str(len(xmlModel.materials)))
        modelMaterials.appendChild(modelNumberMaterials)
        
        for xmlMaterial in xmlModel.materials:         
            material = doc.createElement("Material")
            material.setAttribute("name", xmlMaterial.name)
            model.appendChild(material)
            
            materialInfo = doc.createElement("Properties")
            material.appendChild(materialInfo)
                        
            materialColor = doc.createElement("Color")
            materialInfo.appendChild(materialColor)
            materialColorText = doc.createTextNode(str(xmlMaterial.color.x) + "," + str(xmlMaterial.color.y) + "," + str(xmlMaterial.color.z))
            materialColor.appendChild(materialColorText)
            
            materialVertices = doc.createElement("NumberOfVertices")
            materialInfo.appendChild(materialVertices)
            materialVerticesText = doc.createTextNode(str(len(xmlMaterial.vertices)))
            materialVertices.appendChild(materialVerticesText)
            
            if len(xmlMaterial.textures) > 0:
                materialTextures = doc.createElement("Textures")
                materialInfo.appendChild(materialTextures)
                
                for texture in xmlMaterial.textures:   
                    materialDiffuseTexture = doc.createElement(texture.name)
                    materialTextures.appendChild(materialDiffuseTexture)
                    materialDiffuseTextureText = doc.createTextNode(texture.filePath)
                    materialDiffuseTexture.appendChild(materialDiffuseTextureText)
            
            vertices = doc.createElement("Vertices")
            material.appendChild(vertices)
            
            for xmlVertex in xmlMaterial.vertices:
                vertexNode = doc.createElement("Vertex")
                vertices.appendChild(vertexNode)
                vertex = doc.createTextNode(str(xmlVertex.position.x) + ", " + str(xmlVertex.position.z) + ", " + str(xmlVertex.position.y) + "," + str(xmlVertex.normal.x) + ", " + str(xmlVertex.normal.z) + ", " + str(xmlVertex.normal.y))
                vertexNode.appendChild(vertex)
    for xmlLamp in xmlScene.lamps:
        lamp = doc.createElement("Lamp")
        lamp.setAttribute("name", "Lamp")
        objects.appendChild(lamp)

        lampInfo = doc.createElement("Properties")
        lamp.appendChild(lampInfo)
        
        lampPositionNode = doc.createElement("Position")
        lampInfo.appendChild(lampPositionNode)
        lampPosition = doc.createTextNode(str(xmlLamp.location.x) + ", " + str(xmlLamp.location.z) + ", " + str(xmlLamp.location.y))
        lampPositionNode.appendChild(lampPosition)
                   
print(doc.toprettyxml(indent="  "))

file.write(doc.toprettyxml(indent="  "))
file.close()